﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WeProjectsModel;
using WeProjects.Filters;
using System.Web.Security;
using WeProjects.Helps;
using WeProjects.Models;
using System.IO;
using DynamicQueryLib;
using System.Reflection;
using LinqKit;

namespace WeProjects.Controllers
{
    [Authorize]
    [InitializeSimpleMembership]
    public class NewsController : Controller
    {
        private ProjectsDBEntities db = new ProjectsDBEntities();

        //
        // GET: /News/
         [AllowAnonymous]
        public ActionResult Index(TagVModel[] tags=null,string keyword="")
        {
            //var newsList = (from n in db.News
            //               where n.isPublic == 1
            //               select n).ToList();
            var newsList = from n in db.News
                            where n.isPublic == 1
                            select n;
             if(!Roles.IsUserInRole("sysadmin"))
             {
                 newsList = newsList.Where(n => n.isPublish == 1);
             }
             ViewBag.Tags = db.Tags.ToList();

             if(tags!=null&&tags.Where(t=>t.Selected).Count()>0)
             {
                 var codes=tags.Where(t=>t.Selected).Select(t=>t.Code);
                 newsList = from n in newsList
                            where (from t in n.Tags join c in codes on t.Code equals c select t).Count() > 0
                            select n;
             }
             
             if(keyword.Trim()!="")
             {
                 newsList = Search(keyword, newsList);
             }

             return View(newsList.OrderByDescending(n=>n.PublishDate).ToList().Select(n=>n.ToNewsViewModel(true)));
        }

         public ActionResult ProjectNews(int projectID)
         {
             var project = db.Projects.Find(projectID);
             {
                 if (project == null)
                 {
                     return HttpNotFound();
                 }
             }
             ViewBag.projectTitle = project.Title;
             ViewBag.projectOwnId = project.OwnerID;
             ViewBag.ProjectID = projectID;

             bool hideCreateButton = true;
             if (Roles.IsUserInRole("sysadmin"))
             {
                 hideCreateButton= false;
             }
             else //Owner of this project
             {
                 string userName=Membership.GetUser().UserName;
                 if (project.Owner != null && project.Owner.Name.ToLower() == userName.ToLower())
                 {
                     hideCreateButton = false;
                 }
             }
             ViewBag.HideCreateButton = hideCreateButton;

             var news = from n in db.News
                        where n.ProjectID == projectID
                        select n;
             return View(news.ToList());
         }
        /// <summary>
        /// 发布状态
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="newsId"></param>
        /// <param name="pub"></param>
        /// <returns></returns>
        public ActionResult NewsPublish(int newsId, int pub)
        {
            var news = db.News.Find(newsId);
            if (news == null)
            {
                return HttpNotFound();
            }
            news.ID = newsId;
            news.isPublish = pub;

            if (ModelState.IsValid)
            {
                db.Entry(news).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("Index");
        }
        /// <summary>
        /// 公开状态
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="newsId"></param>
        /// <param name="pub"></param>
        /// <returns></returns>
        public ActionResult NewsPublic(int projectId, int newsId, int pub)
        {
            var project = db.Projects.Find(projectId);
            var news = db.News.Find(newsId);
            if (project == null || news == null)
            {
                return HttpNotFound();
            }
            news.ID = newsId;
            news.isPublic = pub;

            if (ModelState.IsValid)
            {
                db.Entry(news).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("ProjectNews", new { projectID = projectId });
        }
        //
        // GET: /News/Details/5
        [AllowAnonymous]
        public ActionResult Details(int id = 0)
        {
            News news = db.News.Find(id);
            if (news == null)
            {
                return HttpNotFound();
            }
            //显示tags标签
            ViewBag.Tags = news.Tags.ToList();

            var path = Path.Combine(Server.MapPath("~/App_Data/NewsPhotos"), news.ID.ToString(), news.ID.ToString() + ".jpg");
            ////string path = Server.MapPath("~/images/computer.png");
            //byte[] imageByteData = System.IO.File.ReadAllBytes(path);
            //string imageBase64Data = Convert.ToBase64String(imageByteData);
            //string imageData = string.Format("data:image/jpg;base64,{0}", imageBase64Data);
            ViewBag.ImageData = Utility.GetImage64String(path);

            bool isNewsVisible = false;
            if (Roles.IsUserInRole("sysadmin"))
            {
                isNewsVisible = true;
            }
            else if (news.Project.Members.Any(m => m.Name == User.Identity.Name))
            {
                isNewsVisible = true;
            }
            else if(news.isPublish!=null&&news.isPublish==1)
            {
                isNewsVisible = true;
            }
            ViewBag.IsVisible = isNewsVisible;//(!Roles.IsUserInRole("sysadmin") && news.isPublish == 0) && !news.Project.Members.Any(m => m.Name == User.Identity.Name);

            return View(news);
        }

        //
        // GET: /News/Create
        public ActionResult Create(int id)
        {
            var project = db.Projects.Find(id);
            if(project==null)
            {
                return HttpNotFound();
            }
            //显示标签，复选框
            ViewBag.Tags = db.Tags.ToList();
            ViewBag.ProjectTitle = project.Title;
            return View(new NewsModel() {ProjectID=id });
        }

        //
        // POST: /News/Create
        [HttpPost]
        [ValidateInput(false)]
        [ValidateAntiForgeryToken]
        public ActionResult Create(NewsModel model, HttpPostedFileBase file, TagVModel[] tags = null)
        {
            if (ModelState.IsValid)
            {
                model.PublishDate = DateTime.Now;
                model.MemberID = int.Parse(Membership.GetUser().ProviderUserKey.ToString());
                News news = new News() { AuthorID=model.MemberID, isPublic=0, isPublish=0, NewsContent=model.NewsContent,
                    ProjectID=model.ProjectID, Title=model.Title, PublishDate=model.PublishDate };
                news = db.News.Add(news);
                foreach(var tag in tags)
                {
                    if(tag.Selected)
                    {
                        news.Tags.Add(db.Tags.Find(tag.Code));
                    }
                }
                db.SaveChanges();
                //return RedirectToAction("Index", new { projectID=news.ProjectID});
                // Verify that the user selected a file
                if (file != null && file.ContentLength > 0)
                {
                    // extract only the fielname
                    var fileName = Path.GetFileName(file.FileName);
                    string fileExt = Path.GetExtension(fileName).ToLower(); 
                    if (fileExt== ".jpg")//Only store file when its extension name show that it is a jpg file.
                    {
                        // store the file inside ~/App_Data/uploads folder
                        var path = Path.Combine(Server.MapPath("~/App_Data/NewsPhotos"), news.ID.ToString());
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        file.SaveAs(Path.Combine(path, news.ID+".jpg"));
                    }
                }

                return RedirectToAction("Details", new { id = news.ID });
            }

            //ViewBag.ProjectID = new SelectList(db.Projects, "ID", "Title", news.ProjectID);
            return View(model);
        }
        //public ActionResult Create([Bind(Include = "Title,NewsContent,PublishDate,ProjectID")] News news)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        db.News.Add(news);
        //        db.SaveChanges();
        //        return RedirectToAction("Index");
        //    }
        //    ViewBag.ProjectID = new SelectList(db.Projects, "ID", "Title", news.ProjectID);
        //    return View(news);
        //}
        //public ActionResult Create(string Title, string NewsContent, int ProjectID, int[] tags)
        //{
        //    var news = new News();

        //    news.Title = Title;
        //    news.NewsContent = NewsContent;

        //    news.PublishDate = DateTime.Now;
        //    news.MemberID = int.Parse(Membership.GetUser().ProviderUserKey.ToString());
        //    news.ProjectID = ProjectID;

        //    db.News.Add(news);
        //    db.SaveChanges();
        //    int newID = db.News.Max(newsid => news.ID);
        //    if (tags != null)
        //    {
        //        foreach (var item in tags)
        //        {
        //            db.Database.ExecuteSqlCommand("insert into NewsTags(NewsID,TagCode) values('" + newID + "','" + item + "')");
        //        }
        //    }
        //    return RedirectToAction("Details", new { id = newID });
        //}

        //
        // GET: /News/Edit/5
        public ActionResult Edit(int id = 0)
        {
            News news = db.News.Find(id);
            if (news == null)
            {
                return HttpNotFound();
            }
            //用户未勾选的
            var tag = from d in db.Tags
                      where !d.News.Any(t => t.ID == id)
                      select d;
            ViewBag.Tags = tag.ToList();
            //用户当前勾选的
            ViewBag.cTags = news.Tags.ToList();

            ViewBag.ProjectID = new SelectList(db.Projects, "ID", "Title", news.ProjectID);
            return View(news.ToNewsViewModel(true));
        }

        //
        // POST: /News/Edit/5

        [HttpPost]
        [ValidateInput(false)]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(News news, HttpPostedFileBase file,TagVModel[] tags=null)
        {
            if (ModelState.IsValid)
            {
                var newsinDB = db.News.Find(news.ID);
                newsinDB.Title = news.Title;
                newsinDB.NewsContent = news.NewsContent;                
                newsinDB.PublishDate = DateTime.Now;
                newsinDB.AuthorID = int.Parse(Membership.GetUser().ProviderUserKey.ToString());
                if (tags != null)
                {
                    foreach(TagVModel t in tags)
                    {
                        Tag dbTag = db.Tags.Find(t.Code);
                        if(!t.Selected&&newsinDB.Tags.Where(x=>x.Code==t.Code).Count()==1)//Tag is deselected.
                        {                            
                            //dbTag.News.Remove(newsinDB);
                            newsinDB.Tags.Remove(dbTag);
                        }
                        else if(t.Selected&&newsinDB.Tags.Where(x=>x.Code==t.Code).Count()==0)//Newly seleted tag.
                        {
                            newsinDB.Tags.Add(dbTag);
                        }
                    }
                    //var r = from t in newsinDB.Tags
                    //        where !db.Tags.Any(t1 => t1.Code == t.Code)
                    //        select t;
                }
                db.Entry(newsinDB).State = EntityState.Modified;
                db.SaveChanges();

                if (file != null && file.ContentLength > 0)
                {
                    // extract only the fielname
                    var fileName = Path.GetFileName(file.FileName);
                    string fileExt = Path.GetExtension(fileName).ToLower();
                    if (fileExt == ".jpg")//Only store file when its extension name show that it is a jpg file.
                    {
                        // store the file inside ~/App_Data/uploads folder
                        var path = Path.Combine(Server.MapPath("~/App_Data/NewsPhotos"), news.ID.ToString());
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        file.SaveAs(Path.Combine(path, news.ID + ".jpg"));
                    }
                }
                return RedirectToAction("Details", new { id = news.ID });
            }
            return View(news);
        }

        //public ActionResult Edit(string Title, string NewsContent, int ProjectID, int[] tags,int ID)
        //{
        //    var news = new News();
        //    news.ID = ID;
        //    news.Title = Title;
        //    news.NewsContent = NewsContent;
        //    news.PublishDate = DateTime.Now;
        //    news.ProjectID = ProjectID;

        //    if (ModelState.IsValid)
        //    {
        //        db.Entry(news).State = EntityState.Modified;
        //        db.SaveChanges();

        //        db.Database.ExecuteSqlCommand("delete from NewsTags where NewsID='" + ID + "'");
        //        if (tags != null)
        //        {
        //            foreach (var item in tags)
        //            {
        //                db.Database.ExecuteSqlCommand("insert into NewsTags(NewsID,TagCode) values('" + ID + "','" + item + "')");
        //            }
        //        }
        //        return RedirectToAction("Details", new { id=ID});
        //    }
        //    //ViewBag.ProjectID = new SelectList(db.Projects, "ID", "Title", news.ProjectID);
        //    return View(news);
        //}

        //
        // GET: /News/Delete/5

        public ActionResult Delete(int id = 0)
        {            
            News news = db.News.Find(id);
            if (news == null)
            {
                return HttpNotFound();
            }
            if (Roles.IsUserInRole("sysadmin") || news.Author.Name.ToLower() == Membership.GetUser().UserName.ToLower())
            {
                return View(news);
            }
            return RedirectToAction("ProjectNews", "News", new { projectID = news.ProjectID });
        }

        //
        // POST: /News/Delete/5

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            News news = db.News.Find(id);
            int projectID = news.ProjectID;
            //var newId = news.ProjectID;
            //db.Database.ExecuteSqlCommand("delete from NewsTags where NewsID='" + id + "'");
            if(news.Tags.Count>0)
            {
                var tags = news.Tags.ToList();
                foreach(var t in tags)
                {
                    news.Tags.Remove(t);
                }
            }
            db.News.Remove(news);
            db.SaveChanges();
            return RedirectToAction("ProjectNews", "News", new { projectID = projectID });
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        private IQueryable<News> Search(string keyword,IQueryable<News> dbNews)
        {
            keyword = keyword.Trim();
            //Get string type properties from Archive
            var properties = GetArchiveProperties<News>();

            //Prepare the filters
            List<DynamicQueryLib.Filter> filterList = new List<DynamicQueryLib.Filter>();
            for (int i = 0; i < properties.Count; i++)// var prop in properties)
            {
                DynamicQueryLib.Filter f = new DynamicQueryLib.Filter();
                if (i == 0)
                {
                    f.Connector = FilterConnectorType.AND;//the first connector must be AND, otherwise, you get a true
                }
                else
                {
                    f.Connector = FilterConnectorType.OR;
                }
                f.PropertyName = properties[i].Name;
                f.PropertyType = typeof(string);
                f.Values.Add(keyword);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }
            var predicate = LambdaExpressionHelper<News>.CreatePredicate<News>(filterList);
            var news = dbNews.AsExpandable();//.Where(a => a.Subject.ActivityID == activityID);
            news = news.Where(predicate);
            //archives = archives.Union(activityArchives.Include("Subject").Include("County").Where(a => a.Subject.Name.Contains(keyword) || a.County.Name.Contains(keyword)));

            //restrict search result according to user role
            //string userName = Membership.GetUser().UserName;
            //if (Roles.IsUserInRole(userName, "ExpertJudge"))
            //{
            //    var exptGroupIDs = from eg in db.ExpertJudges.Find(userName).ExpertGroups//.Subject.ID;
            //                       select eg.ID;
            //    archives = archives.Where(a => exptGroupIDs.Contains((int)(a.ExpertGroupID == null ? -1 : a.ExpertGroupID)));
            //}

            //if (Roles.IsUserInRole("CountyAdmin"))
            //{
            //    ProfileBase profile = ProfileBase.Create(userName);
            //    string countyCode = (string)profile["CountyCode"];
            //    archives = archives.Where(a => a.CountyCode.Trim() == countyCode.Trim());
            //}
            //return View(archives);
            return news;
        }

        private List<PropertyInfo> GetArchiveProperties<T>()
        {
            var properties = typeof(T).GetProperties(BindingFlags.DeclaredOnly
                                                           | BindingFlags.Public
                                                           | BindingFlags.Instance)
                                                           .Where(p => p.PropertyType == typeof(string)).ToList();
            return properties;
        }
    }
}